import {cloneDeep} from "lodash";
import {h, resolveComponent} from "vue";
import options from '@/components/render/slots/el-select.tsx'
import buttonSlot from '@/components/render/slots/el-button.ts'
import tableSlot from "@/components/render/slots/el-table.jsx"

const componentChild = {
  'el-select': options,
  'el-button': buttonSlot,
  'table-query': tableSlot,
  'el-table': tableSlot,
}

function vModel(dataObject, defaultValue) {
  dataObject.modelValue = defaultValue
  dataObject.value = defaultValue;
  // dataObject.value = defaultValue;
  dataObject['onUpdate:modelValue'] = (val) => {
    this.$emit("update:modelValue", val)
    this.$emit('input', val)
  }
}

function mountSlotFiles(h, confClone, children) {
  const childObjs = componentChild[confClone.__config__.tag]
  if (childObjs) {
    Object.keys(childObjs).forEach(key => {
      const childFunc = childObjs[key]
      if (confClone.__slot__ && confClone.__slot__[key]) {
        children.push(childFunc(h, confClone, key))
      }
    })
  }
}

function emitEvents(confClone) {
  ['on', 'nativeOn'].forEach((attr) => {
    const eventKeyList = Object.keys(confClone[attr] || [])
    eventKeyList.forEach((key) => {
      const val = confClone[attr][key]
      if (typeof val === 'string') {
        confClone[attr][key] = (event) => this.$emit(val, event)
      }
    })
  })
}

function buildDataObject(confClone, dataObject) {
  Object.keys(confClone).forEach(key => {
    const val = confClone[key]
    if (key === '__vModel__') {
      vModel.call(this, dataObject, confClone.__config__.defaultValue)
    } else if (dataObject[key] !== undefined) {
      if (dataObject[key] === null
        || dataObject[key] instanceof RegExp
        || ['boolean', 'string', 'number', 'function'].includes(typeof dataObject[key])) {
        dataObject[key] = val
      } else if (Array.isArray(dataObject[key])) {
        dataObject[key] = [...dataObject[key], ...val]
      } else {
        dataObject[key] = { ...dataObject[key], ...val }
      }
    } else {
      dataObject[key] = val
    }
  })

  // 清理属性
  clearAttrs(dataObject)
}

function clearAttrs(dataObject) {
  delete dataObject.__config__
  delete dataObject.__slot__
  delete dataObject.__methods__
}

function makeDataObject() {
  return {

  }
}

export default {
  props: {
    conf: {
      type: Object,
      required: true
    }
  },
  render() {
    const dataObject = {}
    const confClone = cloneDeep(this.conf)
    const children = this.$slots.default() || []

    mountSlotFiles.call(this, h, confClone, children)

    // 将字符串类型的事件，发送为消息
    emitEvents.call(this, confClone)

    // 将json表单配置转化为vue render可以识别的 “数据对象（dataObject）”
    buildDataObject.call(this, confClone, dataObject)

    return h(resolveComponent(this.conf.__config__.tag), dataObject, children)
  }
}
